/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.metashare.grah.pogo

import net.metashare.grah.logic.EdgePredicate
import net.metashare.grah.logic.Equals
import net.metashare.grah.logic.Predicate
import net.metashare.grah.logic.True
import net.metashare.grah.meta.MetaContext

import net.metashare.grah.NodeHandler
import net.metashare.grah.GraphObjectDecorator
import net.metashare.grah.Graph
import net.metashare.grah.Node
import net.metashare.grah.MetaInvocationException
import net.metashare.grah.ResultGraph

/**
 *
 * @author dsherema
 */

/* this is an expando! */



 class PogoNode implements NodeHandler, Node/*implements GroovyInterceptable*/ {
  def MetaContext context;
  def GroovyObject object;
  def GraphObjectDecorator decorator = PogoDecorator.instance
  def Graph graph;
  def NodeHandler handler = decorator.getDefaultNodeHandler()
  def static boolean debug = false


  def localProperties = ["context", "object", "graph"]


  public  PogoNode(Object o) {

    object = o
    //o.metaClass.propertyMissing = { name -> this."$name"}
    //o.metaClass.propertyMissing = { name, args -> this."$name" = args}
  }


   def Node wrap(Object o) {
     decorator.wrap(o)
   }

   def Object unwrap(Node n) {
     decorator.unwrap(o)
   }

  def methodMissing(String name, args) {
    def result
    if (object) {
//      println "Node - looking for method called" + name
      def metaMethod = object.metaClass.getMetaMethod(name, args)

      if (metaMethod) {
        result = metaMethod.invoke(object, args)
      }
      else {
        throw new MetaInvocationException()
      }
    }
    return result
  }

  def propertyMissing(String name) {
    def result
    if (object)
      return object.metaClass.getProperty(name)
    else {
      throw new MetaInvocationException()
    }

  }

  def propertyMissing(String name, args) {
    def result
    if (object) {
//      println "Node - looking for method called" + name
      if (object.metaClass.hasProperty(name, args))
        object.metaClass.setProperty(name, args)
    }
    else {
      throw new MetaInvocationException()
    }

  }

//  def getProperty( String name )
//  {
//    if (  localProperties.contains( name ) )
//        {
//         println "Locating property for name: $name - localProperty "
//          return this.getProperty( name )
//        }
//
//    else return object.getProperty(name)
//  }
//
//  def void setProperty( String name, Object value)
//  {
//     if ( localProperties.contains(name) )
//     {
//      println "Property for name: $name is local to Node"
//       this.setProperty( name, value)
//     }
//
//    else
//          object."$name" = value
//  }

  /* need test code */


  def ResultGraph edges(Predicate p) {
    ResultGraph rg = new ResultGraph( graph, graph)
    List edges = graph.edges(new EdgePredicate(new Equals(this), True.instance, True.instance))
    edges.each() {
      rg.output.add(it)
    }

    rg.inputs=graph

    return rg
  }


  def Boolean isWrapped() { return true }

  def GroovyObject getUnwrapped() {
    return object


  }

  /* for mutable graphs */

  def ResultGraph connect(Node node) {
    /*TODO*/
    return new ResultGraph()

  }

  def ResultGraph direct(Node node) {
    /*TODO*/
    return new ResultGraph()


  }


  def ResultGraph neighbors(Predicate p = True.instance) {
    /*TODO*/
    return new ResultGraph()

  }

  def String dump() {
    println "THIS NODE WRAPS: $object (original class:)" + node.unwrapped.getMetaClass().getClass()
  }



 }
